package com.gz.springcloud.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.gz.springcloud.entity.Member;
import com.gz.springcloud.entity.Result;
import com.gz.springcloud.handler.CustomGlobalBlockHandler;
import com.gz.springcloud.service.MemberService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

@Slf4j
@RestController
public class MemberController {

    @Resource
    private MemberService memberService;

    @PostMapping("/member/save")
    public Result save(@RequestBody Member member) {
        int affected = memberService.save(member);
        if (affected>0) {
            return Result.success("添加会员成功 member-service-nacos-provider-10004", affected);
        }else {
            return Result.error("401","添加会员失败 member-service-nacos-provider-10004");
        }
    }

//    @GetMapping("/member/get")
//    public Result getMemberById(@RequestParam(value = "id") Long id) {
    @GetMapping("/member/get/{id}")
    public Result getMemberById(@PathVariable("id") Long id) {
        Member member = memberService.queryMemberById(id);
        if (member!=null) {
            return Result.success("查询成功 member-service-nacos-provider-10004",member);
        }else {
            return Result.error("402","查询的id不存在 member-service-nacos-provider-10004");
        }
    }


    /**  热点限流
     * 1.@SentinelResource : 指定sentinel限流资源
     * 2.value = "news" 表示sentinel限流资源 名称,由程序员指定
     * 3. blockHandler = "newsBlockHandler": 当出现限流时，由newsBlockHandler方法进行处理
     */
    @GetMapping("/news")
    @SentinelResource(value = "news",blockHandler = "newsBlockHandler")
    public Result queryNews(@RequestParam(value = "id",required = false) String id,
                         @RequestParam(value = "type",required = false) String type) {
        return Result.success("返回id=" + id + " 新闻 from DB");
    }

    public Result newsBlockHandler(String id, String type,
                                   BlockException blockException) {

        return Result.error("401","查询id="+id+" 的新闻触发热点限流保护");
    }

    private static int num = 0;
    //1.fallback java异常处理类
    //2.blockHandler 限流异常处理类
    //3.exceptionsToIgnore = {NullPointerException.class}表示NullPointerException的异常用默认的异常处理，即500报错
    //不写fallbackClass，默认两个方法在同一个类，写了就表示fallback方法在指定类中
    @GetMapping("/t1")
    //触发限流规则
    @SentinelResource(value = "method1",
            fallbackClass = CustomGlobalBlockHandler.class,
            fallback = "fallbackHandlerMethod1",
            blockHandlerClass = CustomGlobalBlockHandler.class,
            blockHandler = "handlerMethod1",
            exceptionsToIgnore = {NullPointerException.class})
    //注意与限流处理类的参数一样，否则无效，限流处理类的参数只比限流类多一个BlockException(或者不加这个参数也行)
    public Result t1() {
        //假定: 当访问t6资源次数是5的倍数时，就出现java异常
        if (++num % 5 == 0) {
            throw new NullPointerException("null指针异常 num=" + num);
        }
        if (num % 6 == 0) {//当访问t6资源次数是6的倍数时,抛出 runtime异常
            throw new RuntimeException("RuntimeException num=" + num);
        }
        log.info("执行t1() 线程id={}", Thread.currentThread().getId());
        return Result.success("200", "t1()执行OK~~");
    }

}
